from django.core.exceptions              import ImproperlyConfigured
from django.db                           import models
from django.template                     import loader
from django.utils.importlib              import import_module
from django.utils.translation            import ugettext_lazy as _
from sitepal.sitebase.util               import iterappmodules
from sitepal.sitetheme.exceptions        import RendererDoesNotExist
from sitepal.sitetheme.models.containers import Container,ContainerManager
from sitepal.sitetheme.models.themes     import Theme
from sitepal.sitetheme.renderers         import BlockRenderer,TemplateBlockRenderer

class BlockManager(ContainerManager):
    def itermodules(self):
        return iterappmodules(submodule='siteapp.blocks')

    def sync_container(self,name,data):
        return super(BlockManager,self).sync_object(name,data)

    def sync_object(self,name,data):
        if 'renderer' in data:
            return ApplicationBlock.objects.sync_object(name,data)
        elif 'template' in data:
            return TemplateBlock.objects.sync_object(name,data)
        else:
            raise ImproperlyConfigured,"Invalid block type"

class Block(Container):
    block_type = models.CharField(_("block type"),max_length=30,editable=False)
    objects    = BlockManager()

    class Meta(Container.Meta):
        verbose_name        = _('block')
        verbose_name_plural = _('blocks')
        app_label           = 'sitetheme'

    @property
    def block_types(self):
        return ('applicationblock','templateblock')

    @property
    def display_classes(self):
        return (u'block',) + tuple(super(Block,self).display_classes)

class ApplicationBlockManager(BlockManager):
    def sync_object(self,name,data):
        created,obj = self.sync_container(name,data)
        try:
            renderer = data['renderer']
            if issubclass(renderer,BlockRenderer):
                obj.renderer_name = '.'.join((renderer.__module__,renderer.__name__))
            else:
                raise ImproperlyConfigured,"Renderer must be a subclas of 'BlockRenderer'"
            return created,obj
        except Exception,e:
            raise ImproperlyConfigured,e

class ApplicationBlock(Block):
    renderer_name = models.CharField(_("renderer name"),editable=False,max_length=250)
    objects       = ApplicationBlockManager()

    class Meta(Block.Meta):
        verbose_name        = _('application block')
        verbose_name_plural = _('application blocks')
        app_label           = 'sitetheme'

    def save(self,*args,**kwargs):
        if not self.block_type:
            self.block_type = 'applicationblock'
        super(ApplicationBlock,self).save(*args,**kwargs)

class TemplateBlockManager(BlockManager):
    def sync_object(self,name,data):
        created,obj = self.sync_container(name,data)
        try:
            obj.template_source = data['template']
            template            = loader.get_template_from_string(obj.template_source)
            return created,obj
        except Exception,e:
            raise ImproperlyConfigured,e

class TemplateBlock(Block):
    source  = models.TextField(_("template source"),max_length=8192)
    objects = TemplateBlockManager()

    class Meta(Block.Meta):
        verbose_name        = _('template block')
        verbose_name_plural = _('template blocks')
        app_label           = 'sitetheme'

    @property
    def render_class(self):
        return TemplateBlockRenderer

    def save(self,*args,**kwargs):
        if not self.block_type:
            self.block_type = 'templateblock'
        super(ApplicationBlock,self).save(*args,**kwargs)

